package pers.cfeng.server.versionManage;

import pers.cfeng.common.SubArray;
import pers.cfeng.server.dataManage.dataItem.DataItem;
import pers.cfeng.server.utils.ByteBufferParser;

import java.util.Arrays;

/**
 * 数据记录实现，一条记录包含在一个DataItem中
 * [TMIN][TMAX][DATA] TMIN 代表的创建该条记录的tid， TMAX代表的是删除该记录的tid
 * 一个entry就是用于操作一个dataItem
 */

public class Entry {
    private static final int OF_TMIN = 0;
    private static final int OF_TMAX = OF_TMIN + 8;
    private static final int OF_DATA = OF_TMAX + 8;

    private long uid;
    private DataItem dataItem;
    private VersionManager versionManager;

    /**
     * 创建一条记录
     */
    public static Entry newEntry(VersionManager versionManger, DataItem dataItem, long uid) {
        Entry entry = new Entry();
        entry.uid = uid;
        entry.dataItem = dataItem;
        entry.versionManager = versionManger;
        return entry;
    }

    /**
     * 加载一条记录dataItem， dataItem的标识就是uid
     */
    public static Entry loadEntry(long uid, VersionManager versionManager) throws Exception {
        DataItem di = ((VersionManagerImpl)versionManager).getDataManager().read(uid);
        return newEntry(versionManager,di,uid);
    }

    public static byte[] wrapEntryRaw(long tid, byte[] data) {
        byte[] tmin = ByteBufferParser.long2Byte(tid);
        byte[] tmax = new byte[8];
        return ByteBufferParser.mergeBytes(tmin, tmax, data);
    }

    public void release() {
        ((VersionManagerImpl)versionManager).releaseEntry(this);
    }

    public void remove() {
        dataItem.release();
    }

    //拷贝byte形式返回数据, 就是读取DataItem中的数据
    public byte[] data() {
        dataItem.rLock();
        try {
            SubArray sa = dataItem.data();
            byte[] data = new byte[sa.end - sa.start - OF_DATA];
            System.arraycopy(sa.raw, sa.start + OF_DATA, data, 0, data.length);
            return data;
        } finally {
            dataItem.rUnLock();
        }
    }

    public long getTmin() {
        dataItem.rLock();
        try {
            SubArray sa = dataItem.data();
            return ByteBufferParser.parseLong(Arrays.copyOfRange(sa.raw, sa.start + OF_TMIN, sa.start + OF_TMAX));
        } finally {
            dataItem.rUnLock();
        }
    }

    public long getTmax() {
        dataItem.rLock();
        try {
            SubArray sa = dataItem.data();
            return ByteBufferParser.parseLong(Arrays.copyOfRange(sa.raw, sa.start + OF_TMAX, sa.start + OF_DATA));
        } finally {
            dataItem.rUnLock();
        }
    }

    public void setTmax(long tid) {
        dataItem.before(); //设置Tmax就是要删除，先进行备份
        try {
            SubArray sa = dataItem.data();
            System.arraycopy(ByteBufferParser.long2Byte(tid), 0, sa.raw, sa.start + OF_TMAX, 8);
        } finally {
            dataItem.after(tid);
        }
    }

    public long getUid() {
        return uid;
    }
}
